/**
 * 
 */
package com.ffcs.crmd.tsp.server.netty.processor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ffcs.crmd.tsp.api.dto.client.TspTaskConnectInfo;
import com.ffcs.crmd.tsp.api.dto.netty.RemotingCommand;
import com.ffcs.crmd.tsp.api.dto.page.PageInfo;
import com.ffcs.crmd.tsp.api.dto.page.RetVo;
import com.ffcs.crmd.tsp.api.netty.INettyProcessor;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.netty.ResponseCode;
import com.ffcs.crmd.tsp.core.util.RemotingUtil;
import com.ffcs.crmd.tsp.core.util.XmlUtil;
import com.ffcs.crmd.tsp.server.application.ApplicationManagerHolder;
import com.ffcs.crmd.tsp.server.core.DataBaseHandler;
import com.ffcs.crmd.tsp.server.core.QuartzSchedulerHandler;
import com.ffcs.crmd.tsp.server.core.RemotingHandler;
import com.ffcs.crmd.tsp.server.manager.JobProcessManager;
import com.ffcs.crmd.tsp.server.manager.TaskRemotingManager;
import com.ffcs.crmd.tsp.server.netty.task.TaskRegisterInfo;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;

/**
 * 功能说明:
 *
 * @author ZHONGFUHUA
 * 
 * @since 
 *
 */
public class QueryTaskConnectInfoProcessor implements INettyProcessor {
    /**
     * 日志
     */
    private final static Logger LOG                 = LoggerFactory.getLogger(LoggerName.RemotingLoggerName);
    
    /**
     * 任务端管理器
     */
    private JobProcessManager   jobProcessManager   = ApplicationManagerHolder.getBean("jobProcessManager", JobProcessManager.class);
    
    /**
     * 任务端管理器
     */
    private TaskRemotingManager taskRemotingManager = ApplicationManagerHolder.getBean("taskRemotingManager", TaskRemotingManager.class);
    
    /**
     * 功能说明:
     * 
     * @param remotingController
     */
    public QueryTaskConnectInfoProcessor(RemotingHandler remotingController, DataBaseHandler dataBaseHandler) {
    }
    
    /**
     * 功能说明:
     * 
     * @param ctx
     * @param request
     * @return
     */
    @Override
    public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) {
        RemotingCommand response = RemotingCommand.createResponseCommand(ResponseCode.SUCCESS);
        String requestXml = new String(request.getBody());
        try {
            LOG.info("SERVER-NETTY: one request to query task connect info is received that body=[{}]", requestXml);
            TspTaskConnectInfo tspTaskConnectInfoVO = (TspTaskConnectInfo) XmlUtil.fromXml(requestXml, TspTaskConnectInfo.class);
            List<Channel> channelList = jobProcessManager.getChannels(tspTaskConnectInfoVO.getJobName());
            List<TspTaskConnectInfo> tspTaskConnectInfoVOList = new ArrayList<TspTaskConnectInfo>();
            RetVo<TspTaskConnectInfo> retVO = new RetVo<TspTaskConnectInfo>();
            for (Channel channel : channelList) {
                TaskRegisterInfo taskRegisterInfo = taskRemotingManager.getTaskRegisterInfo(channel);
                if(taskRegisterInfo != null){
                    TspTaskConnectInfo rtspTaskConnectInfoVO = new TspTaskConnectInfo();
                    rtspTaskConnectInfoVO.setInstanceId(QuartzSchedulerHandler.getInstanceId());
                    rtspTaskConnectInfoVO.setClusterName(QuartzSchedulerHandler.getClusterName());
                    rtspTaskConnectInfoVO.setConnectTime(new Date(taskRegisterInfo.getLastUpdateTimestamp()));
                    rtspTaskConnectInfoVO.setIpAddress(RemotingUtil.parseChannelRemote(channel));
                    rtspTaskConnectInfoVO.setIdentity(taskRegisterInfo.getIdentity());
                    rtspTaskConnectInfoVO.setClientId(taskRegisterInfo.getClientId());
                    tspTaskConnectInfoVOList.add(rtspTaskConnectInfoVO);
                }
            }
            
            Collections.sort(tspTaskConnectInfoVOList, new Comparator<TspTaskConnectInfo>() {
                @Override
                public int compare(TspTaskConnectInfo o1, TspTaskConnectInfo o2) {
                    if (!o1.getIdentity().equals(o2.getIdentity())) {
                        return o1.getIdentity().compareTo(o2.getIdentity());
                    }
                    
                    if (!o1.getIpAddress().equals(o2.getIpAddress())) {
                        return o1.getIpAddress().compareTo(o2.getIpAddress());
                    }
                    return 0;
                }
            });
            
            if (tspTaskConnectInfoVO.getPageNumber() != null && tspTaskConnectInfoVO.getPageSize()!= null 
                && tspTaskConnectInfoVO.getPageNumber() > 0 && tspTaskConnectInfoVO.getPageSize() > 0) {
                int pageNumber = tspTaskConnectInfoVO.getPageNumber();
                int pageSize = tspTaskConnectInfoVO.getPageSize();
                int totalCounts = tspTaskConnectInfoVOList.size();
                int first = PageInfo.getPageBeginSize(pageSize, pageNumber);
                int end = PageInfo.getPageEndSize(first, pageSize, totalCounts);
                
                List<TspTaskConnectInfo> ntspTaskConnectInfoVOList = new ArrayList<TspTaskConnectInfo>();
                ntspTaskConnectInfoVOList.addAll(tspTaskConnectInfoVOList.subList(first, end));
                PageInfo<TspTaskConnectInfo> pageInfo = new PageInfo<TspTaskConnectInfo>(ntspTaskConnectInfoVOList);
                pageInfo.calcAndJudge(pageSize, pageNumber, totalCounts, ntspTaskConnectInfoVOList);
                retVO.setPageInfo(pageInfo);
            } else {
                retVO.setDataList(tspTaskConnectInfoVOList);
            }
            response.setBody(XmlUtil.toXml(retVO).getBytes());
        } catch (Exception e) {
            LOG.error("SERVER-NETTY: query task connect info processor[{}] exception:", requestXml, e);
            String responseBody = String.format("query task connect info processor exception:%s", e.getMessage());
            response.setCode(ResponseCode.FAIL);
            response.setBody(responseBody.getBytes());
        }
        return response;
    }
}
